import React from 'react';
import { Field, Button, Message, Dialog, Input, Balloon } from '@teamix/ui';
import { navigate } from 'utils/router';
import FilePanel from 'components/filePanel';
import Editor from 'components/editor';
import FileBasicForm from 'components/fileBasicForm';
import UILessAssociateTask from 'components/UILessAssociateTask';
import exceed from 'utils/apimap';
import { getAllFiles } from 'api';
import utils from 'utils';
import intl from '../../../../../../../../locale';

const { Tooltip } = Balloon;
const { pathResource, resourceSubject } = window.FORCE;

export default class EditorFiles extends React.Component {
  constructor(props) {
    super(props);
    this.field = new Field(this);
    this.state = {
      visible: false,
      blob: ' ',
      submitting: false,
      existFileList: [],
      task_ids: '',
    };
  }

  componentDidMount() {
    this.getBlob(null, (blob) => {
      let content = blob;
      // TODO 内容为空时，不知为何是没处理的xhr对象
      if (blob.statusText && !blob.responseText) {
        content = '';
      }
      this.field.setValue('content', content);
    });

    window.onbeforeunload = function () {
      return intl.get({
        id: 'code-assets.containers.editorFiles.AreYouSureYouWant',
        defaultMessage: '确定离开此页面？',
      });
    };

    if (window.FORCE.pathResource.isEmpty !== 'true') {
      getAllFiles()
        .then((result) => {
          result.shift();
          this.setState({
            existFileList: result,
          });
        })
        .catch((err) => {
          console.log(err);
        });
    }
  }

  // 获取文件内容
  // 接口见：http://gitlab.alibaba-inc.com/help/api/repositories.md#raw-file-content
  getBlob = (path, cb) => {
    const { resourcePath } = this.props;
    exceed
      .forceFetch({
        api: 'projects.blobs',
        params: { projectId: pathResource.id },
        data: {
          filepath: path || resourcePath,
          ref:
            resourceSubject.revisionType === 'branch'
              ? `refs/heads/${resourceSubject.revision}`
              : resourceSubject.revision,
        },
      })
      .then((result) => {
        this.setState({
          blob: result,
        });

        cb && cb(result);
      });
  };

  // 修改文件
  // 接口见：http://gitlab.alibaba-inc.com/help/api/repository_files.md
  // newPath, oldPath 2个参数在路径没改动时传一样的
  editFile = (formData, commit_message) => {
    const { resourcePath } = this.props;
    const revision = resourceSubject.revision || 'master';
    const { branch_name, content, task_ids } = formData;
    const file_path = this.field.getValue('file_path');

    const resourcePathArr = resourcePath.split('/');
    const fullPath = resourcePathArr.slice(0, resourcePathArr.length - 1).join('/');

    const new_path = fullPath ? `${fullPath}/${file_path}` : file_path;
    const old_path = resourcePath;

    return exceed
      .fetch({
        api: 'projects.files.edit.associateTask',
        data: {
          project_id: pathResource.id,
          task_ids,
          new_path,
          old_path,
          commit_message,
          branch_name,
          content,
        },
      })
      .then(() => {
        Message.success({
          title: intl.get({
            id: 'code-assets.containers.editorFiles.SubmittedSuccessfully',
            defaultMessage: '提交成功',
          }),
        });

        this.props.updateData({
          hasPush: true,
        });

        window.onbeforeunload = null; // 清空阻止跳转事件
        navigate(
          `/${pathResource.fullPath}/blob/${utils.revisionEncodeURI(revision)}/${encodeURIComponent(
            new_path,
          )}`,
          { state: { forceUpdate: true } },
        );
        this.setState({ submitting: false });
      })
      .fail(() => {
        this.setState({ submitting: false });
      });
  };

  onFormSave = () => {
    const { resourcePath } = this.props;
    this.field.validate((errors) => {
      if (!errors) {
        if (this.state.submitting) return;
        this.setState({ submitting: true });
        const formData = this.field.getValues();
        const commit_message = formData.commit_message_content
          ? `${formData.commit_message_title}\n${formData.commit_message_content}`
          : formData.commit_message_title;
        formData.file_path = resourcePath;
        if (this.state.task_ids) {
          formData.task_ids = this.state.task_ids;
        }
        this.editFile(formData, commit_message);
      } else if (errors.file_path) {
        // 如果是路径为填，提示输入路径
        Message.error({
          title: errors.file_path.errors[0],
        });

        this.setState({ submitting: false });
      }
    });
  };

  cancleConfirm = () => {
    const { resourcePath } = this.props;
    const revision = resourceSubject.revision || 'master';
    this.confirmResult = window.confirm(
      intl.get({
        id: 'code-assets.containers.editorFiles.YouAreEditingTheFile',
        defaultMessage: '您正在编辑文件，是否确认离开？',
      }),
    );
    if (!this.confirmResult) {
      return false;
    } else {
      window.onbeforeunload = null; // 清空阻止跳转事件
      navigate(
        `/${pathResource.fullPath}/blob/${utils.revisionEncodeURI(revision)}/${resourcePath}`,
        { state: { forceUpdate: true } },
      );
    }
  };

  onOpen = () => {
    this.field.validate((errors) => {
      if (!errors) {
        this.setState({
          visible: true,
        });
      }
    });
  };

  onClose = () => {
    this.setState({
      visible: false,
    });
  };

  nameValidator = (rule, value, callback) => {
    const { resourcePath } = this.props;
    const resourcePathArr = resourcePath.split('/');
    const fullPath = resourcePathArr.slice(0, resourcePathArr.length - 1).join('/');

    const newFilePath = `${fullPath}${fullPath && '/'}${value}`;
    const oldFilePath = resourcePath;

    const { existFileList } = this.state;

    if (!value) {
      callback();
      return;
    }
    if (/^(?!(\/)).+$/.test(value) === false) {
      callback(
        intl.get({
          id: 'code-assets.containers.editorFiles.AFileCannotStartWith',
          defaultMessage: '文件不能直接以 / 开头',
        }),
      );
      return;
    }
    if (!new RegExp('^[\\u4e00-\\u9fa5a-z A-Z0-9_\\-\\.\\/]*$').test(value)) {
      callback(
        intl.get({
          id: 'code-assets.containers.editorFiles.TheNameCanOnlyContain',
          defaultMessage: '名称只能包含中英文、数字、"_"、"-"、"."以及空格',
        }),
      );
      return;
    }

    existFileList.forEach((item) => {
      if (newFilePath === item.path && newFilePath !== oldFilePath) {
        callback(
          intl.get({
            id: 'code-assets.containers.editorFiles.TheFileAlreadyExists',
            defaultMessage: '文件已存在',
          }),
        );
      }
    });

    callback();
  };

  render() {
    const { resourcePath } = this.props;
    const revision = resourceSubject.revision || 'master';
    const resourcePathArr = resourcePath.split('/');
    const fullPath = resourcePathArr.slice(0, resourcePathArr.length - 1).join('/');
    const fileName = resourcePathArr[resourcePathArr.length - 1];
    const { init } = this.field;
    const { blob } = this.state;
    const file_path = this.field.getValue('file_path');
    const fileRootPath = fullPath && fullPath.split('/').join(' / ');
    return (
      <div className="project-new-files">
        <FilePanel>
          <FilePanel.Header>
            {fileRootPath && (
              <span style={{ marginRight: 16 }}>{fileRootPath && `${fileRootPath} /`}</span>
            )}

            <Input
              placeholder={intl.get({
                id: 'code-assets.src.utils.locale.EnterAFileName',
                defaultMessage: '请输入文件名',
              })}
              {...init('file_path', {
                initValue: fileName,
                rules: [
                  {
                    required: true,
                    message: intl.get({
                      id: 'code-assets.src.utils.locale.TheFileNameIsRequired',
                      defaultMessage: '文件名为必填项',
                    }),
                  },
                  { validator: this.nameValidator },
                ],
              })}
              style={{ width: '300px' }}
              autoFocus
            />

            <span
              style={{
                margin: '4px 0px 4px 8px',
                fontSize: '14px',
                color: '#e62412',
              }}
            >
              {this.field.getState('file_path') === 'error'
                ? this.field.getError('file_path')
                : null}
            </span>
          </FilePanel.Header>
          <FilePanel.Body noPadding>
            <Editor
              {...init('content', {
                initValue: blob,
              })}
              fileName={fileName}
              genWatermarkimage={this.props.genWatermarkimage}
            />

            <div style={{ margin: '20px 0' }}>
              <Button
                disabled={
                  this.field.getValue('file_path') === null ||
                  this.field.getState('file_path') === 'error'
                }
                type="primary"
                onClick={this.onOpen}
              >
                {intl.get({
                  id: 'code-assets.containers.editorFiles.Save',
                  defaultMessage: '保存',
                })}
              </Button>
              <Button onClick={this.cancleConfirm} style={{ marginLeft: 16 }} type="normal">
                {intl.get({
                  id: 'code-assets.containers.editorFiles.Cancel',
                  defaultMessage: '取消',
                })}
              </Button>
              <Dialog
                title={
                  <Tooltip
                    trigger={
                      <div className="file-form-title">
                        {intl.get(
                          {
                            id: 'code-assets.containers.editorFiles.SubmitToRevision',
                            defaultMessage: '提交到 {revision}',
                          },
                          { revision },
                        )}
                      </div>
                    }
                    align="t"
                  >
                    <span style={{ wordBreak: 'break-all' }}>
                      {intl.get({
                        id: 'code-assets.containers.editorFiles.Submit',
                        defaultMessage: '提交到',
                      })}
                      {revision}
                    </span>
                  </Tooltip>
                }
                visible={this.state.visible}
                onOk={this.onFormSave}
                onCancel={this.onClose}
                onClose={this.onClose}
                style={{ width: '600px' }}
                okProps={{
                  children: intl.get({
                    id: 'code-assets.containers.editorFiles.Submitted',
                    defaultMessage: '提交',
                  }),
                  loading: this.state.submitting,
                }}
                cancelProps={{
                  children: intl.get({
                    id: 'code-assets.containers.editorFiles.Cancel',
                    defaultMessage: '取消',
                  }),
                }}
              >
                <FileBasicForm
                  field={this.field}
                  defaultCommitMsg={intl.get(
                    {
                      id: 'code-assets.containers.editorFiles.UpdateFilepath',
                      defaultMessage: '更新 {filePath}',
                    },
                    { filePath: file_path },
                  )}
                />
                <UILessAssociateTask
                  useBy="submit"
                  onChange={(items) => {
                    if (!items.map) {
                      return;
                    }
                    const task_ids = items.map((item) => {
                      return item._id;
                    });
                    this.setState({
                      task_ids: task_ids.join(','),
                    });
                  }}
                />
              </Dialog>
            </div>
          </FilePanel.Body>
        </FilePanel>
      </div>
    );
  }
}
